This page last changed on Oct 24, 2006 by alan.cassar.

This cookbook is a basic explaination of how we access web-services hosted on external servers together with some explaination of document styles.

Calling Axis (provided) Calculator.jws from Mule

How much configuration you need to do when you use Axis to call a web service depends on the style of the document. What do we mean by style? The style we are referring to here are those famous RPC Encoded style, Document Literal style, Document Wrapped...

When web-services' fame started to grow and people started using web-services, the RPC Encoded style was the most widely used. This is the main reason why Axis assumes RPC Encoded style when no style is implicitly specified. There are quite some interesting articles on the net describing the difference between styles, one of which being http://atmanes.blogspot.com/2005/03/wrapped-documentliteral-convention.html

So let us get to the juicy part now. If we would like to call the Calculator.jws, which is a service provided with the Axis distribution (throughout this example, the Calculator.jws will be assumed to be residing on an external service, such as tomcat), from within Mule using the Axis transport, basically we need to do the following. The first important thing to do is open its WSDL and look for the style of the document. As said before, when no implicit style is enforced, Axis will use RPC Encoded, but we cannot always assume that! Let us say that we would like to call the method add() from the Calculator.jws. In the WSDL, we find the following:

...
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
...
<wsdl:input name="addRequest">
   <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://DefaultNamespace" use="encoded"/>
</wsdl:input>
...

From these 4 lines, we can deduce that our service is using RPC Encoded style. Using this style is the easiest using Axis, because it requires no further configuration. In fact our component which accesses this service will look something as follows:

<mule-descriptor name="CalculatorBridge" implementation="org.mule.components.simple.BridgeComponent">
   <inbound-router>
      <endpoint address="vm://calculator.in"/>
   </inbound-router>
   <outbound-router>
      <router className="org.mule.routing.outbound.OutboundPassThroughRouter">
         <endpoint address="axis:http://localhost:8080/axis/Calculator.jws?method=add"/>
      </router>
   </outbound-router>
</mule-descriptor>

As we can clearly see, this is a very simple request where the only thing we need to configure is the endpoint address of the outbound router. We just need to specify where the service is hosted together with the method we need to execute. Calling a doc/lit service will not be as simple as this RPC encoded call though. We will see this later in this cookbook.

Hosting a Doc/Lit service in Mule using Axis

When hosting a service within the Mule framework using the Axis transport, the possibility to choose the required style is provided. This is further explained in http://mule.mulesource.org/wiki/display/MULE/Configuring+Axis#ConfiguringAxis-DocumentStyles

Therefore, if we have a very simple HelloWorld service

package org.mule.myServices.HelloWorld;

public class HelloWorld implements IHelloWorld 
{
   public String sayHello(String src)
   {
      return "Hello " + src; 
   }

}

which we would like to expose as a Doc/Lit service, all the configuration required is shown below:

<mule-descriptor name="HelloWorld" implementation="org.mule.myServices.HelloWorld">
   <inbound-router>
      <endpoint address="axis:http://localhost:81/services"/>
   </inbound-router>
   <properties>
      <property name="style" value="document"/>
      <property name="use" value="Literal"/>
   </properties>
</mule-descriptor>

As it can be clearly seen, all the configuration required is setting the document style as a property on the component itself.

Calling a Doc/Lit service from Mule using Axis

Calling this above explained service using Axis is not as easy as calling an RPC hosted service. The main reason behind this is that in Doc/Lit request, the parameters of the call are not wrapped in a tag which defines the method name. The request parameters are all part of the SOAP Body. This leads to a constraint... the names of the tags which surround the parameters must match with the ones of the actual service, otherwise, the SOAP engine will never recognize which method it needs to call. Furthermore, in Doc/Lit requests, SOAP requests can be checked for syntax before actually parsing the document and calling the requested method. This allows for syntax errors to be identified before the actual document interpretation is started. This feature is not available in RPC encoded style.

After that small explanation about Doc/Lit style, let us now see how Axis can be used to make Doc/Lit requests to the above hosted service. Just as in the Calculator.jws, we can confirm that the service is a Doc/Lit service by looking at the WSDL. The following lines say it all:

...
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
   <wsdl:operation name="sayHello">
...
      <wsdl:input name="sayHelloRequest">
         <wsdlsoap:body use="literal"/>
      </wsdl:input>

      <wsdl:output name="sayHelloResponse">
         <wsdlsoap:body use="literal"/>
      </wsdl:output>
...

To complete this Doc/Lit request, we said above that we have to abide with some strict rules for naming. These rules include naming for:

  • Namespace
  • Parameters
  • Methods

The list of names mentioned above must be fetched in the WSDL document of the web service and used to make the doc/lit request to the service. The following line from the WSDL defines the target namespace that we need to use in our request

<schema elementFormDefault="qualified" targetNamespace="http://myServices.mule.org">

We also need to look for the parameter names and the method names:

...
wsdl:message name="sayHelloResponse">
   <wsdl:part element="impl:sayHelloReturn" name="sayHelloReturn"/>
</wsdl:message>
...
<wsdl:operation name="sayHello" parameterOrder="in0">

Now that we have collected all the data, we can formulate our request:

<mule-descriptor name="HelloWorldBridge" implementation="org.mule.components.simple.BridgeComponent">
   <inbound-router>
      <endpoint address="vm://HelloWorld.in"/>
   </inbound-router>
   <outbound-router>
      <router className="org.mule.routing.outbound.OutboundPassThroughRouter">
         <endpoint address="axis:http://localhost:81/services/HelloWorld?method=sayHello">
            <properties>
               <property name="style" value="document"/>
               <property name="use" value="Literal"/>
               <map name="soapMethods">
                  <list name="qname{sayHello:http://myServices.mule.org}">
                     <entry value="in0;string;in"/>
                     <entry value="sayHelloReturn;string;out"/>
                  </list>
               </map>
            </properties>
         </endpoint>
      </router>
   </outbound-router>
</mule-descriptor>

Note the properties on the outbound router. First of all, we are adding the Document Literal properties to the endpoint. Following that, we include the data collected from the WSDL in our request. The property soapMethods includes all this. This property contains a list of all the parameters of the service together with the type and whether they are in or out parameters, together with the qualified name defined by name="qname{sayHello:http://http://myServices.mule.org} which basically takes the form of <method_name:namespace_name>

Document generated by Confluence on Nov 27, 2006 10:27